package com.zhao.framework;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;

/**
 * 
 * full data binding convert
 * 从shindig移植过来的转换器不知道怎么处理List<String>这种情况。
 * 因为不知道怎么拿list<String>的ParameterizedType。
 * jackson包网上的评价不错，功能完备，性能卓越。
 */
public class Json {
	protected static final Log logger = LogFactory.getLog(Json.class);
	
	private static ObjectMapper mapper = new ObjectMapper();
	static{
		mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		mapper.configure(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT,true);
	}
	/**
	 * @param <T>
	 * @param json a url encoded json string.
	 * @param clz
	 * @return object of clz, or null
	 */
	public static <T> T urlDecode(String json,Class<T> clz){
		String jsonDecoded;
		try {
			jsonDecoded = URLDecoder.decode(json,"UTF-8");
		} catch (UnsupportedEncodingException e1) { 
			return null;
		}
		try {
			return mapper.readValue(jsonDecoded, clz);
		} catch (Exception e) {
			return null;
		}
	}
	/**
	 * @param <T>
	 * @param json a json string
	 * @param clz
	 * @return a object of clz.
	 */
	public static <T> T to(String json,Class<T> clz){
		try {
			return mapper.readValue(json, clz);
		} catch (Exception e) {
			logger.error(e);
			return null;
		}
	}
	/**
	 *  Example: Map<String,User> result = Json.to(string, new TypeReference<Map<String,User>>() { });
	 * @param <T>
	 * @param json
	 * @param trf
	 * @return
	 */
	public static <T> T to(String json,TypeReference<?> trf){
		try {
			return mapper.readValue(json, trf);
		} catch (Exception e) {
			return null;
		}
	}
	/**
	 * Example: Map<String,User> result = Json.to(string, new TypeReference<Map<String,User>>() { });
	 * @param <T>
	 * @param json
	 * @param trf
	 * @return
	 */
	public static <T> T urlDecode(String json,TypeReference<?> trf){
		String jsonDecoded;
		try {
			jsonDecoded = URLDecoder.decode(json,"UTF-8");
		} catch (UnsupportedEncodingException e1) { 
			return null;
		}
		try {
			return mapper.readValue(jsonDecoded, trf);
		} catch (Exception e) {
			return null;
		}
	}
	/**
	 * object to json string
	 * @param obj
	 * @return
	 */
	public static String from(Object obj){
		try {
			return mapper.writeValueAsString(obj);
		} catch (Exception e) {
			logger.warn(e);
			return null;
		}
	}
}
